package accel.movement;

import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import accel.dataholders.Character;
import accel.movement.MovementProperties.Direction;
import accel.movement.MovementProperties.Strength;
import accel.movements.Attack;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.Toast;

public class MovementDetector implements SensorEventListener{

	private SensorManager sensorManager;
	private long lastUpdate;
	private float x2,y2,z2;
	private final float NOISE = (float)3;
	private final float HARD = NOISE + 3;
	private final int INTERVAL = 250;
	private Context parent;
	private boolean initialized = false;
	private AttackSet movementSet;
	LinkedList <Movement3D>movs = new LinkedList<Movement3D>();
	private Lock movsLock = new ReentrantLock();
	
	public enum FightType {Training, Combat}
	public FightType fightType = FightType.Combat;
	
	private static MovementDetector instance = null;
	public static final float lightIsUpTo = 7;
	
	private MovementDetector(Context parent)
	{
		this.parent = parent;
		sensorManager = (SensorManager) parent.getSystemService(parent.SENSOR_SERVICE);
	}
	
	public static synchronized MovementDetector getInstance(Context p)
	{
		if (instance == null && p!=null)
			instance = new MovementDetector(p);
		return instance;
	}
	
	public void setMovementSet(AttackSet m)
	{
		this.movementSet = m;
	}
	
	public void registerSensor()
	{
		sensorManager.registerListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_NORMAL);
		lastUpdate = System.currentTimeMillis();
	}
	
	public void unregisterSensor()
	{
		sensorManager.unregisterListener(this);
	}
	
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
		
	}

	public void onSensorChanged(SensorEvent event) {
		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
			getAccelerometer(event);
		
	}
	
	private void getAccelerometer(SensorEvent event) {
  	  
    	long actualTime = System.currentTimeMillis();
    	if (actualTime - lastUpdate < INTERVAL)
			return;
		lastUpdate = actualTime;
		float[] values = event.values;

		float x = values[0];
		float y = values[1];
		float z = values[2];
		String info = "";
		if (initialized)
		{
			MovementProperties X,Y,Z;
			if (Math.abs(x - x2) > NOISE)
			{//info += "x - " + (x>x2?"left":"right");
				X = new MovementProperties(Math.abs(x - x2)>HARD ? Strength.Hard : Strength.Light, x>x2 ? Direction.Minus : Direction.Plus);
			}
			else
				X = new MovementProperties(Strength.None, Direction.None);
			if (Math.abs(y - y2) > NOISE)
			{//info += (info.length() == 0 ? "y - ":" : y - ") + (y>y2?"up":"down");
				Y = new MovementProperties(Math.abs(y - y2)>HARD ? Strength.Hard : Strength.Light, y>y2 ? Direction.Plus : Direction.Minus);
			}
			else
				Y = new MovementProperties(Strength.None, Direction.None);
			if (Math.abs(z - z2) > NOISE)
			{//info += (info.length() == 0 ? "z - " : " : z - ") + (z>z2?"forth":"back");
				Z = new MovementProperties(Math.abs(z - z2)>HARD ? Strength.Hard : Strength.Light, z>z2 ? Direction.Plus : Direction.Minus);
			}
			else
				Z = new MovementProperties(Strength.None, Direction.None);
			movsLock.lock();
			movs.add(new Movement3D(X,Y,Z));
			Attack a = movementSet.process(movs);
			movsLock.unlock();
			if (a != null)
			{
				Toast.makeText(parent, parent.getString(a.name()), Toast.LENGTH_SHORT).show();
				Character.instance.addExp(fightType == FightType.Combat ? Character.instance.learningSpeed() : Character.instance.learningSpeed() / 2);
			}
			//if (info.length() > 0)
				//Toast.makeText(parent, info, Toast.LENGTH_SHORT).show();
		}
		else
			initialized = true;
		x2 = x;
		y2 = y;
		z2 = z;
	}

}
